#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'walkingsky'

import argparse
import re
from models.stock_service import StockService 
import sys
import datetime, time
import os
import pandas as pd
from pandas.core.frame import DataFrame
from models.utils import rollback_days, print_aligned, find_files
from models.efinance.stock.config import INDUSTRY_SAVE_PATH
from config.data_config import BOARDS_HASH, COL_NAME
from config.env_config import DATA_FILE_PATH

lists_csv_file = './temp_data/股票板块数据/stock_board_lists.csv'
details_csv_file = './temp_data/股票板块数据/stock_board_details.csv'
sleep_time = 1

last_trading_day = None


def get_board_detail(board_code, debug=False):
    res2_json = StockService().get_board_details(board_code)
    df_details = DataFrame(res2_json.get('data').get('diff'))
    df_details.insert(0, '日期', datetime.date.today().strftime('%Y-%m-%d'))
    df_details = df_details.rename(columns={
        'f2': '最新价', 'f3': '涨跌幅', 'f62': '主力流入净额', 
        'f66': '超大单流入净额', 'f184': '主力流入净比', 
        'f69': '超大单流入净占比', 'f12': '代码', 'f14': '名称',
        'f72': '大单流入净额', 'f75': '大单流入净占比', 
        'f78': '中单流入净比', 'f81': '中单流入净占比',
        'f84': '小单流入净比', 'f87': '小单流入净占比'
    })

    df_details = df_details.loc[:, [
        '日期', '名称', '代码', '最新价', '涨跌幅', '主力流入净额', 
        '主力流入净比', '超大单流入净额', '超大单流入净占比', 
        '大单流入净额', '大单流入净占比', '中单流入净比', 
        '中单流入净占比', '小单流入净比', '小单流入净占比'
    ]]

    # 修复索引删除范围错误
    if len(df_details) > 15:
        start = 10
        end = len(df_details) - 5
        if start < end:  # 确保范围有效
            df_details = df_details.drop(index=range(start, end))

    if debug:
        print(df_details)
        print(len(df_details))

    # 修复CSV写入时包含多余索引列的问题
    if os.path.exists(details_csv_file):
        df_details.to_csv(details_csv_file, mode='a', header=False, index=False)
    else:
        df_details.to_csv(details_csv_file, mode='w', index=False)


def write2csv(debug: bool = False):
    '''
    更新行业板块和行业板块内股票列表数据

    参数:
    debug(bool):是否打印调试信息
    '''
    # 用循环替代递归，修复栈溢出风险
    max_retries = 5
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            res_json = StockService().get_board_lists()
            break  # 成功获取数据，退出循环
        except Exception as e:
            retry_count += 1
            print(f"获取板块列表失败，第{retry_count}次重试: {e}")
            time.sleep(sleep_time)
            if retry_count >= max_retries:
                print("达到最大重试次数，获取板块列表失败")
                return
    
    df = DataFrame(res_json.get('data').get('diff'))
    df.insert(0, '日期', datetime.date.today().strftime('%Y-%m-%d'))
    df = df.rename(columns={
        'f2': '最新价', 'f3': '涨跌幅', 'f4': '涨跌额', 
        'f20': '总市值', 'f5': '成交量', 'f6': '成交额', 
        'f12': '代码', 'f14': '名称', 'f104': '上涨家数', 
        'f105': '下跌家数'
    })
    
    if debug:
        print(df)
    
    # 修复CSV写入时包含多余索引列的问题
    if os.path.exists(lists_csv_file):
        df.to_csv(lists_csv_file, mode='a', header=False, index=False)
    else:
        df.to_csv(lists_csv_file, mode='w', index=False)    

    # 修复异常处理不完善导致无限重试的问题
    for i in res_json.get('data').get('diff'):
        max_attempts = 3
        attempt = 0
        while attempt < max_attempts:
            try:
                get_board_detail(i['f12'], debug)
                break
            except Exception as e:
                attempt += 1
                print(f"获取板块详情失败，第{attempt}次重试: {e}")
                time.sleep(2 * sleep_time)
                if attempt >= max_attempts:
                    print(f"超过最大重试次数，放弃获取{i['f12']}")
        time.sleep(sleep_time)


def clean(n=30):
    '''
    清理n个交易日之前的数据，默认30个交易日
    '''
    date = rollback_days(n)
    date = pd.to_datetime(date.strftime('%Y-%m-%d'))

    if not os.path.exists(lists_csv_file) or not os.path.exists(details_csv_file):
        print("行业数据文件不存在，更新数据")
        write2csv()
        return
        

    df = pd.read_csv(lists_csv_file)
    # 判断是否有超过日期的数据,没有就退出
    df['日期'] = pd.to_datetime(df['日期'])
    tempset = df[df['日期'] <= date]
    if len(tempset) == 0:
        return
        
    subset = df[df['日期'] > date]
    subset.to_csv(lists_csv_file, mode='w', index=False)  # 修复索引问题

    df = pd.read_csv(details_csv_file)
    df['日期'] = pd.to_datetime(df['日期'])    
    subset = df[df['日期'] > date]
    subset.to_csv(details_csv_file, mode='w', index=False)  # 修复索引问题


def write_board_stocks_(board_code: str, board_name: str, days: int = 30):
    '''
    按天数获取板块内所有股票的历史行情数据，按照特定名称写入csv文件
    东方财富会对访问请求做页面验证了，所以请求数达到一定程度就会拒绝访问了
    '''
    import models.efinance as ef
    max_retries = 3
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            res_json = StockService().get_board_stocks(board_code)
            break
        except Exception as e:
            retry_count += 1
            print(f"获取板块列表失败，第{retry_count}次重试: {e}")
            if retry_count >= max_retries:
                print("达到最大重试次数，获取板块列表失败")
                return

    file_name = os.path.join(DATA_FILE_PATH, f"{board_code}_{board_name}.csv")  # 修复路径拼接
    i = 1
    if not os.path.exists(file_name):        
        for stock in res_json.get('data').get('diff'):
            len_data = len(res_json.get('data').get('diff'))
            stock_code = str(stock['f13']) + '.' + stock['f12']
            df = ef.stock.get_history_daily_klines(stock_code=stock_code, days=days)
            df.insert(0, '代码', stock['f12'])
            df.insert(1, '名称', stock['f14'])
            time.sleep(sleep_time)                       
            
            # 修复索引问题
            if os.path.exists(file_name):
                df.to_csv(file_name, mode='a', header=False, index=False)
            else:
                df.to_csv(file_name, mode='w', header=True, index=False)
                
            print(f'\t%4d只股票......%.1f%%' % (len_data, i/len_data*100), end='\r', flush=True)
            i += 1
    else:
        # 获取和数据相差的天数
        df = pd.read_csv(file_name, dtype={'代码': str}, parse_dates=['日期'])
        date = df['日期'].max()
        today = datetime.datetime.today()
        days = (today - date).days
        if datetime.datetime.now().hour < 16:
            days = days - 1
        if days > 0:
            for stock in res_json.get('data').get('diff'):
                len_data = len(res_json.get('data').get('diff'))
                stock_code = str(stock['f13']) + '.' + stock['f12']
                df = ef.stock.get_history_daily_klines(stock_code=stock_code, days=days)
                df.insert(0, '代码', stock['f12'])
                df.insert(1, '名称', stock['f14'])
                time.sleep(sleep_time)
                
                # 修复索引问题
                df.to_csv(file_name, mode='a', header=False, index=False)                
                print(f'\t%4d只股票......%.1f%%' % (len_data, i/len_data*100), end='\r', flush=True)
                i += 1               
        else:
            print('无更新。。。', end='')
    print('')


def write_board_stocks(board_code: str, board_name: str, days: int = 30):
    '''
    按天数获取板块内所有股票的历史行情数据，按照特定名称写入csv文件
    使用tushare接口访问
    '''
    global last_trading_day

    # 导入tushare
    import tushare as ts
    max_retries = 3
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            res_json = StockService().get_board_stocks(board_code)
            break
        except Exception as e:
            retry_count += 1
            print(f"获取板块列表失败，第{retry_count}次重试: {e}")
            if retry_count >= max_retries:
                print("达到最大重试次数，获取板块列表失败")
                return

    # 修复路径拼接问题
    file_name = os.path.join(DATA_FILE_PATH, f"{board_code}_{board_name}.csv")
    pro = ts.pro_api(os.getenv('tushare_token'))
    
    stock_codes = ''
    # 拼接tushare接口使用的ts_code参数（股票代码集合）
    for stock in res_json.get('data').get('diff'):
        len_data = len(res_json.get('data').get('diff'))
        if stock['f13'] == 0:
            stock_code = str(stock['f12']) + '.sz'
        elif stock['f13'] == 1:
            stock_code = str(stock['f12']) + '.sh'
        else:
            stock_code = str(stock['f12']) + '.bj'
        
        stock_codes = stock_codes + ',' + stock_code 

    if not os.path.exists(file_name): 
        # 出现错误，就会重试
        max_attempts = 3
        attempt = 0
        df = None
        
        while attempt < max_attempts:
            attempt += 1 
            # 修复tushare接口fields参数格式错误
            df = pro.daily(
                ts_code=stock_codes,
                start_date=(datetime.datetime.now() - datetime.timedelta(days=days)).strftime('%Y%m%d'),
                end_date=datetime.datetime.now().strftime('%Y%m%d'),
                fields="ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount"
            )
            
            # 判断数据是否正常
            if df.columns.size < 11:
                print(f'返回的数据不正常，第{attempt}次重试\t{stock_code}\t{stock["f12"]}')
                time.sleep(sleep_time)
                continue
            else:
                break
        
        if df is None or df.columns.size < 11:
            print("无法获取有效的股票数据")
            return
            
        df.columns = ['代码', '日期', '开盘价', '最高价', '最低价', '收盘价', 
                     '昨收价', '涨跌额', '涨跌幅', '成交量', '成交额']
        df.insert(1, '股票名称', '-')

        # 替换数组里的名称
        for stock in res_json.get('data').get('diff'):
            if stock['f13'] == 0:
                stock_code = str(stock['f12']) + '.SZ'
            elif stock['f13'] == 1:
                stock_code = str(stock['f12']) + '.SH'
            else:
                stock_code = str(stock['f12']) + '.BJ'

            df.loc[df['代码'] == stock_code, '股票名称'] = stock['f14']

        # 转换日期格式 yyyymmdd=>yyyy-mm-dd
        df['日期'] = df['日期'].astype(str).apply(lambda x: f"{x[:4]}-{x[4:6]}-{x[6:]}")
        time.sleep(sleep_time)                       

        # 修复索引问题
        df.to_csv(file_name, mode='w', header=True, index=False)

    else:
        # 获取和数据相差的天数
        df = pd.read_csv(file_name, dtype={'代码': str}, parse_dates=['日期'])
        
        # 修复未定义变量stock_code的问题
        # 先获取第一个股票代码用于检查
        if not res_json.get('data').get('diff'):
            print("板块内没有股票数据")
            return
            
        first_stock = res_json.get('data').get('diff')[0]
        if first_stock['f13'] == 0:
            stock_code = str(first_stock['f12']) + '.SZ'
        elif first_stock['f13'] == 1:
            stock_code = str(first_stock['f12']) + '.SH'
        else:
            stock_code = str(first_stock['f12']) + '.BJ'
        
        # 查找'代码'列等于code的行
        filtered_df = df[df['代码'].str.lower() == stock_code.lower()]
        
        # 检查是否找到匹配的行
        if not filtered_df.empty:
            # 返回'日期'列的最大日期
            max_date = filtered_df['日期'].max()
        else:
            max_date = None

        if max_date is None or last_trading_day is None:
            max_date = datetime.datetime.now() - datetime.timedelta(days=30)
        else:
            # 修复数据类型不匹配问题
            last_trading_day_dt = pd.to_datetime(last_trading_day, format='%Y%m%d')
            if last_trading_day_dt == max_date:
                print('无更新。。。')
                return
                    
        # 出现错误，就会重试
        max_attempts = 3
        attempt = 0
        new_df = None
        
        while attempt < max_attempts:
            attempt += 1 
            # 修复tushare接口fields参数格式错误
            new_df = pro.daily(
                ts_code=stock_codes,
                start_date=(max_date + datetime.timedelta(days=1)).strftime('%Y%m%d'),
                end_date=datetime.datetime.now().strftime('%Y%m%d'),
                fields="ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount"
            )
            
            # 判断数据是否正常
            if new_df.columns.size < 11:
                print(f'返回的数据不正常，第{attempt}次重试\t{stock_code}\t{first_stock["f12"]}')
                time.sleep(sleep_time)
                continue
            else:
                break
        
        if new_df is None or new_df.columns.size < 11 or new_df.empty:
            print("没有获取到新的股票数据")
            return
        
        new_df.columns = ['代码', '日期', '开盘价', '最高价', '最低价', '收盘价', 
                         '昨收价', '涨跌额', '涨跌幅', '成交量', '成交额']
        new_df.insert(1, '股票名称', '-')

        # 替换数组里的名称
        for stock in res_json.get('data').get('diff'):
            if stock['f13'] == 0:
                stock_code = str(stock['f12']) + '.SZ'
            elif stock['f13'] == 1:
                stock_code = str(stock['f12']) + '.SH'
            else:
                stock_code = str(stock['f12']) + '.BJ'

            new_df.loc[new_df['代码'] == stock_code, '股票名称'] = stock['f14']

        # 转换日期格式 yyyymmdd=>yyyy-mm-dd
        new_df['日期'] = new_df['日期'].astype(str).apply(lambda x: f"{x[:4]}-{x[4:6]}-{x[6:]}")            

        time.sleep(sleep_time)
        # 修复索引问题
        new_df.to_csv(file_name, mode='a', header=False, index=False)                


def write_all_boards():
    '''
    遍历所有版块，获取所有股票的历史行情数据，并写入csv文件
    '''
    df = pd.read_csv(INDUSTRY_SAVE_PATH)
    for i, row in df.iterrows():
        print(row['板块名称'])
        write_board_stocks(board_code=row['行业代码'], board_name=row['板块名称'])
        print(f"获取{row['板块名称']}({row['行业代码']})的历史行情数据完成\n")
        time.sleep(sleep_time)


def list_boards(from_file: bool = False):
    '''
    列表显示所有版块名称和代码
    '''
    if from_file:
        df = pd.read_csv(INDUSTRY_SAVE_PATH)
        for i, row in df.iterrows():
            if i % 5 == 0:
                print('')
            print(f'%2s-%s-%-8s\t\t' % (str(i), row['行业代码'], row['板块名称']), end='')
    else:        
        for i in BOARDS_HASH:
            if i['index'] % 5 == 0:
                print('')
            print(f'%2s-%s-%-8s\t\t' % (str(i['index']), i['code'], i['name']), end='')
    print('')


def get_bord_name_by_code(board_code: str):
    '''
    通过板块的代码查找板块的名称
    '''
    for i in BOARDS_HASH:
        if i['code'] == board_code:
            return i['name']
    return ''


def get_bord_code_by_name(board_name: str):
    '''
    通过板块的名称查找板块的代码
    '''
    for i in BOARDS_HASH:
        if i['name'] == board_name:
            return i['code']
    return ''


def sort_a(board: str, n: int = 5, m: int = 5, x: int = 10, ascending: bool = False, col_name: str = '涨跌幅'):
    '''
    按列名“col_name”检索(board)板块内，前n天交易日内x次(统计每只进入排序的股票的次数)正排序或倒排序前m排名的股票信息
    '''
    # board参数兼容 代码和名称  
    if board.find('BK') == -1:
        board_name = board
        board_code = get_bord_code_by_name(board_name=board)
    else:
        board_code = board
        board_name = get_bord_name_by_code(board)
        
    if not board_code:
        print(f"找不到板块: {board}")
        return
        
    # col_name 兼容名称和序列号
    if (not col_name in COL_NAME) and col_name.isdigit():
        col_name = int(col_name)
        if col_name <= 11:
            col_name = COL_NAME[col_name]
        else:
            print('col_name参数设置错误')
            return

    print(f'按“{col_name}”检索({board_name})板块内，前{n}天交易日内{x}次(统计每只进入排序的股票的次数)出现在{"后" if ascending else "前"}{m}排名的股票信息')
    if x > n or not col_name in COL_NAME:
        print('参数设置不合理')
        return
    
    write_board_stocks(board_code=board_code, board_name=board_name)
    file_name = os.path.join(DATA_FILE_PATH, f"{board_code}_{board_name}.csv")  # 修复路径拼接
    df = pd.read_csv(file_name, dtype={'代码': str}, parse_dates=['日期'])
    date = rollback_days(n)
    date = pd.to_datetime(date.strftime('%Y-%m-%d'))
    df = df.drop(df[df['日期'] < date].index)
    df = df.sort_values(by=['日期', col_name], ascending=[False, ascending])
    
    grouped = df.groupby(['日期']).head(m)
    result = grouped['代码'].value_counts()
    
    for i, stock in result.items():
        if stock >= x:  # 只显示满足x次条件的股票
            for j, v in grouped.iterrows():
                if v['代码'] == i:
                    print(f'%-8s\t%s\t%d' % (v['股票名称'], i, stock))
                    break


def get_last_trading_day():
    '''
    获取上一个交易日
    '''
    # 导入tushare
    import tushare as ts
    pro = ts.pro_api(os.getenv('tushare_token'))
    # 修复获取交易日错误，使用上证指数代码000001.SH
    df = pro.daily(ts_code='000001.SH', start_date='', end_date='', limit=1)
    if not df.empty:
        return df.iloc[0]['trade_date']
    return None


def zhangdiefu(file_name: str, days: int = 10):
    '''
    抓取单个行业数据文件，计算里面股票的涨跌幅为正的累加值
    条件 ：涨跌幅为正，且日期在最近10天之内
    '''
    # 修复路径拼接问题
    file_path = os.path.join(DATA_FILE_PATH, file_name)
    try:
        df = pd.read_csv(file_path, dtype={'代码': str}, parse_dates=['日期'])
    except Exception as e:
        print(f'文件处理错误: {e}')
        return
        
    # 按code和name分组，计算涨跌幅为正的累加值
    result = df.groupby(['代码', '股票名称']).apply(
        lambda group: 
        group[
                (group['日期'] >= group['日期'].max() - pd.Timedelta(days=days)) &
                (group['涨跌幅'] > 0)
            ]['涨跌幅'].sum()
    ).reset_index(name='涨幅累加值')

    # 按涨幅累加值降序排序
    result = result.sort_values('涨幅累加值', ascending=False)
    print_aligned(result)


def zhangdietianshu(file_name: str, days: int = 10):
    '''
    抓取单个行业数据文件，计算里面股票的涨跌天数对比值
    条件 ：且日期在最近10天之内
    '''
    # 修复路径拼接问题
    file_path = os.path.join(DATA_FILE_PATH, file_name)
    try:
        df = pd.read_csv(file_path, dtype={'代码': str}, parse_dates=['日期'])
    except Exception as e:
        print(f'文件处理错误: {e}')
        return
        
    # 1. 转换日期列
    df['日期'] = pd.to_datetime(df['日期'])

    # 2. 按code和name分组，筛选每个组内最近10天的数据
    filtered_df = df.groupby(['代码', '股票名称']).apply(lambda group: 
        group[group['日期'] >= group['日期'].max() - pd.Timedelta(days=days)]
    ).reset_index(drop=True)

    # 3. 计算每个组的正、负天数
    result = filtered_df.groupby(['代码', '股票名称']).apply(lambda group: pd.Series({
        '正天数': (group['涨跌幅'] > 0).sum(),
        '负天数': (group['涨跌幅'] < 0).sum()
    })).reset_index()

    # 4. 计算比值（处理负天数为0的情况）
    result['涨跌比'] = result.apply(
        lambda row: row['正天数'] / row['负天数'] if row['负天数'] > 0 else float('inf'),
        axis=1
    )

    # 5. 按比值降序排序
    result = result.sort_values('涨跌比', ascending=False)

    # 6. 输出结果
    print_aligned(result[['代码', '股票名称', '涨跌比', '正天数', '负天数']])


def cross_stars(file_name: str, days: int = 10, threshold: float = 0.01, 
                each_other_ratio: float = 3, ratio_open_price: float = 0.03, group_count: bool = False):
    """
    统计日K数据中的墓碑十字星和蜻蜓十字星数量
    
    参数:
    file_name (str): 数据文件
    days(init): 几天的数据
    threshold (float): 判断十字星的阈值（实体相对开盘价的比例），默认为0.01（即1%）
    each_other_ratio(float): 两个影线的高度比的阈值 默认3
    ratio_open_price(float): 影线>开盘价的阈值（限定影线要有足够的高度）默认0.03
    group_count(bool): 是否分组统计墓碑十字星，蜻蜓十字星的数量 默认false
    
    输出:df格式数据
    """
    import numpy as np

    # 修复路径拼接问题
    file_path = os.path.join(DATA_FILE_PATH, file_name)
    try:
        df = pd.read_csv(file_path, dtype={'代码': str}, parse_dates=['日期'])
    except Exception as e:
        print(f'文件处理错误: {e}')
        return
    
    # 1. 转换日期列
    df['日期'] = pd.to_datetime(df['日期'])

    # 2. 按code和name分组，筛选每个组内最近指定天数的数据
    data = df.groupby(['代码', '股票名称']).apply(lambda group: 
        group[group['日期'] >= group['日期'].max() - pd.Timedelta(days=days)]
    ).reset_index(drop=True)
    
    # 计算实体大小（开盘价与收盘价的绝对差值）
    data['实体大小'] = abs(data['收盘价'] - data['开盘价'])
    
    # 计算上影线和下影线长度
    data['上影线'] = data['最高价'] - data[['开盘价', '收盘价']].max(axis=1)
    data['下影线'] = data[['开盘价', '收盘价']].min(axis=1) - data['最低价']
    
    # 十字星核心条件：实体极小（实体大小 < 开盘价的1%）
    # 避免开盘价为0导致除零错误
    data['是否十字星'] = (data['实体大小'] / np.where(data['开盘价'] == 0, 1, data['开盘价'])) < threshold
    
    # 墓碑十字星条件
    data['墓碑十字星'] = data['是否十字星'] & \
                        (data['上影线'] > each_other_ratio * data['下影线']) & \
                        (data['上影线'] / np.where(data['开盘价'] == 0, 1, data['开盘价']) > ratio_open_price)
    
    # 蜻蜓十字星条件
    data['蜻蜓十字星'] = data['是否十字星'] & \
                        (data['下影线'] > each_other_ratio * data['上影线']) & \
                        (data['下影线'] / np.where(data['开盘价'] == 0, 1, data['开盘价']) > ratio_open_price)
    
    
    if group_count:
        # 按股票代码分组统计
        result = data.groupby(['代码', '股票名称']).agg(
            墓碑十字星数量=('墓碑十字星', 'sum'),
            蜻蜓十字星数量=('蜻蜓十字星', 'sum')
        ).reset_index()
        
        print_aligned(result)
    else:
        # 过滤 '墓碑十字星' 和 '蜻蜓十字星' 为0的数据
        print_aligned(data[(data['蜻蜓十字星'] > 0) | (data['墓碑十字星'] > 0)] \
                      [['代码', '股票名称', '日期', '上影线', '下影线', '蜻蜓十字星', '墓碑十字星']])


def test1():
    '''测试函数'''
    StockService().get_board_stocks(board_code='BK0737')


def test():
    df = pd.read_csv(os.path.join(DATA_FILE_PATH, 'BK0737_软件开发.csv'), dtype={'代码': str}, parse_dates=['日期'])
    # 查找'代码'列等于code的行
    filtered_df = df[df['代码'].str.lower() == '002987.sz']
    last_trading_day = get_last_trading_day()

    # 检查是否找到匹配的行
    if not filtered_df.empty:
        # 返回'日期'列的最大日期
        max_date = filtered_df['日期'].max()
        print("最大日期是:", max_date)
    else:
        max_date = None

    if max_date and last_trading_day:
        days = (pd.Timestamp(last_trading_day) - max_date).days
        print(days)
        print((datetime.datetime.now() - datetime.timedelta(days=days)).strftime('%Y%m%d'))
        if datetime.datetime.now().hour < 16:
            days = days - 1
        print(days)
        print((datetime.datetime.now() - datetime.timedelta(days=days)).strftime('%Y%m%d'))

        print((datetime.datetime.strptime(last_trading_day, '%Y%m%d') - datetime.timedelta(days=days)).strftime('%Y%m%d'))
        print((max_date + datetime.timedelta(days=1)).strftime('%Y%m%d'))

    max_date = datetime.datetime.now() - datetime.timedelta(days=30)
    print((max_date + datetime.timedelta(days=1)).strftime('%Y%m%d'))

    if last_trading_day:
        print(pd.to_datetime(last_trading_day, format='%Y%m%d') == max_date)


def main():
    # 创建解析器
    parser = argparse.ArgumentParser(
        description="处理股票数据的脚本，支持多种参数配置",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    
    # 添加参数（按功能分组）
    board_group = parser.add_argument_group("获取行业板块信息")
    board_group.add_argument(
        "--board", 
        action="store_true", 
        help="执行更新行业板块和行业板块内股票列表数据的操作"
    )

    board_group.add_argument(
        "--list-board", 
        action="store_true", 
        help="列表显示所有版块名称和代码"
    )

    stock_group = parser.add_argument_group("获取所有股票数据")
    stock_group.add_argument(
        "--dailyK", 
        action="store_true", 
        help="执行获取所有股票日K数据信的操作"
    )
    stock_group.add_argument(
        "--sleeptime",
        type=float,  
        default=1,
        required=False, 
        help="url请求间隔时间（单位秒）"
    )
        
    data_group = parser.add_argument_group("数据分析处理")
    data_group.add_argument(
        "--zhangdiefu", 
        action="store_true", 
        help="分析股票日K数据的涨跌幅"
    )
    data_group.add_argument(
        "--zhangdietianshu", 
        action="store_true", 
        help="分析股票日K数据的涨跌天数"
    )
    data_group.add_argument(
        "--cross-star", 
        action="store_true", 
        help="分析股票日K数据中的十字星"
    )
    data_group.add_argument(
        "--board-name", 
        type=str,
        default='', 
        help="行业板块文件的名称(默认为空：分析所有板块)"
    )
    data_group.add_argument(
        "--days", 
        type=int, 
        default=10, 
        help="设置分析最近多少天的数据（默认10天）"
    )
    data_group.add_argument(
        "--cross-t", 
        type=float, 
        default=0.01, 
        help="设置十字星的阈值（实体相对开盘价的比例），默认为0.01（即1%%）"
    )
    data_group.add_argument(
        "--cross-r", 
        type=float, 
        default=3, 
        help="设置十字星两个影线的高度比的阈值 默认3"
    )
    data_group.add_argument(
        "--cross-p", 
        type=float, 
        default=0.03, 
        help="设置十字星影线>开盘价的阈值（限定影线要有足够的高度）默认0.03"
    )
    data_group.add_argument(
        "--cross-gp", 
        action="store_true", 
        help="设置十字星是否分组统计墓碑十字星，蜻蜓十字星的数量 默认false"
    ) 

    sort_group = parser.add_argument_group("数据排序") 
    sort_group.add_argument(
        "--sort", 
        action="store_true", 
        help="股票数据排序：按列名“col_name”检索(board)板块内，前n天交易日内x次(统计每只进入排序的股票的次数)正排序或倒排序前m排名的股票信息"
    ) 
    sort_group.add_argument(
        "--asc",
        action="store_true",
        help="设置排序规则，默认False (正排序) 配置该参数则为 True（倒排序）"
    )
    sort_group.add_argument(
        "--col-name",
        type=str,
        default="涨跌幅",
        help="检索排序数据的列名，默认（涨跌幅）"
    )
    sort_group.add_argument(
        "--b-name",  # 修复参数名
        type=str,
        help="行业板块名称，可以是代码，也可以是名称"
    )
    sort_group.add_argument(
        "--n",
        type=int,
        default=5,
        help="天数 默认5"
    )
    sort_group.add_argument(
        "--m",
        type=int,
        default=5,
        help="排名 默认5"
    )
    sort_group.add_argument(
        "--x",
        type=int,
        default=10,
        help="次数 默认10"
    )


    # 解析参数
    args = parser.parse_args()
    
    # 使用参数
    if args.board:
        from chinese_calendar import is_workday
        # 先清理数据
        clean()

        date = datetime.date.today()
        # 判断是否为交易日
        if is_workday(date) and datetime.datetime.isoweekday(date) < 6:
            # 判断是否已经有了今天的数据
            if os.path.exists(lists_csv_file):
                df = pd.read_csv(lists_csv_file)
                df['日期'] = pd.to_datetime(df['日期'])
                date_today = pd.to_datetime(datetime.date.today().strftime('%Y-%m-%d'))
                subset = df[df['日期'] == date_today]
                if len(subset) < 2:
                    write2csv()
            else:
                write2csv()

    if args.list_board:
        list_boards()

    if args.dailyK:
        global last_trading_day, sleep_time
        last_trading_day = get_last_trading_day()
        sleep_time = args.sleeptime
        write_all_boards()

    if args.zhangdiefu or args.zhangdietianshu or args.cross_star:
        board_filename_str = args.board_name
        days = int(args.days)

        files = find_files(pattern=board_filename_str, directory=DATA_FILE_PATH)
        
        if len(files) == 0:
            print('没有找到文件')
        else:
            for file_name in files:
                print(f'文件名：{file_name}')
                if args.zhangdiefu:
                    zhangdiefu(file_name=file_name, days=days)
                elif args.zhangdietianshu:
                    zhangdietianshu(file_name=file_name, days=days)
                elif args.cross_star:
                    cross_stars(
                        file_name=file_name, 
                        days=days,
                        threshold=args.cross_t,
                        each_other_ratio=args.cross_r, 
                        ratio_open_price=args.cross_p,
                        group_count=args.cross_gp
                    )

    if args.sort:
        # 修复参数名不匹配问题
        sort_a(
            board=args.b_name, 
            n=args.n, 
            m=args.m, 
            x=args.x, 
            ascending=args.asc, 
            col_name=args.col_name
        )


if __name__ == "__main__":
    main()
    # test()
    # cross_stars('BK0910_专用设备.csv', 0.01)
